//
//  PurchasedViewController.swift
//  GhostWorld
//
//  Created by Kam on 2018/7/27.
//  Copyright © 2018 LKGood. All rights reserved.
//

import UIKit
import SwiftyStoreKit
import PKHUD

private let purchasedItemCellIdentifier = "PurchasedItemCell"
private let noDataCellIdentifier = "NoDataTableCell"
private let purchasedHeaderViewIdentifier = "PurchasedHeaderView"

class PurchasedViewController: BaseViewController {
  
  struct Content {
    enum ContentType: String {
      case album = "album"
      case group = "group"
    }
    
    var date: Date
    var contentType: ContentType
    var id: String
    var name: String
    var coverURL: URL
  }
  
  struct IAPPurchaseBasicInfo {
    var productID: String
    var date: Date
  }
  
  // MARK: - IBOutlets
  
  @IBOutlet private weak var tableView: UITableView!
  
  // MARK: - Private vars
  
  private var exchangedContents: [Content]?
  private var codeContents: [Content]?
  private var iapPurchaseBasicInfos: [IAPPurchaseBasicInfo]?
  private var iapContents: [Content]?
  
  private var selectedSimpleGroup: SimpleGroup?
  private var selectedAlbumIdentifier: Int = 0
  
  // MARK: - Private methods
  
  private func prepareUI() {
    tableView.contentInset = UIEdgeInsets.init(top: 20, left: 0, bottom: 0, right: 0)
    tableView.scrollIndicatorInsets = tableView.contentInset
    tableView.register(UINib(nibName: noDataCellIdentifier, bundle: nil), forCellReuseIdentifier: noDataCellIdentifier)
    tableView.register(UINib(nibName: purchasedHeaderViewIdentifier, bundle: nil), forHeaderFooterViewReuseIdentifier: purchasedHeaderViewIdentifier)
  }
  
  @objc private func loadExhcnagedContents() {
    exchangedContents = nil
    API.shared.requestAPI (
      APIURLStrings.getExchangedContents,
      method: .get,
      header: API.shared.memeberHeader,
      successCallback: { json in
        // exchanges
        if let contentsJSONArray = json["contents"].array {
          self.exchangedContents = contentsJSONArray.map {
            Content (
              date: Date(fromString: $0["date"].stringValue, format: .dateTime)!,
              contentType: Content.ContentType(rawValue: $0["type"].stringValue)!,
              id: $0["id"].stringValue,
              name: $0["name"].stringValue,
              coverURL: URL(string: "\(APIURLStrings.imagePrefix)\($0["cover"].stringValue)")!
            )
          }
        }
        
        // code
        if let contentsJSONArray = json["code_consumption"].array {
          self.codeContents = contentsJSONArray.map {
            Content (
              date: Date(fromString: $0["date"].stringValue, format: .dateTime)!,
              contentType: Content.ContentType(rawValue: $0["type"].stringValue)!,
              id: $0["id"].stringValue,
              name: $0["name"].stringValue,
              coverURL: URL(string: "\(APIURLStrings.imagePrefix)\($0["cover"].stringValue)")!
            )
          }
        }
        self.tableView.reloadSections(IndexSet(integersIn: 0...1), with: .automatic)
    }) { (message, code) in
      self.tableView.reloadSections(IndexSet(integersIn: 0...1), with: .automatic)
    }
  }
  
  private func loadLocalIAPContents() {
    if let localIAPContents = EntityManager.fetch(IAPPurchasedItem.self, fetchType: .all) {
      iapContents = localIAPContents.map {
        Content (
          date: $0.date!,
          contentType: Content.ContentType(rawValue: $0.contentType!)!,
          id: $0.id!,
          name: $0.name!,
          coverURL: URL(string: $0.coverURLString!)!
        )
      }.sorted { return $0.date < $1.date }
      tableView.reloadSections(IndexSet(integer: 2), with: .automatic)
    }
  }
  
  private func addNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(loadExhcnagedContents), name: .reloadPurchasedHistory, object: nil)
  }
  
  // MARK: - Public vars
  
  
  
  // MARK: - Lifecycle
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    prepareUI()
    loadExhcnagedContents()
    loadLocalIAPContents()
    addNotifications()
  }
  
  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }
  
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ShowGroupFromPurchased" {
      let albumsViewController = segue.destination as! AlbumsViewController
      albumsViewController.simpleGroup = selectedSimpleGroup
    } else if segue.identifier == "ShowAlbumDetailFromPurchased" {
      let albumDetailViewController = segue.destination as! AlbumDetailViewController
      albumDetailViewController.albumIdentifier = selectedAlbumIdentifier
    }
  }
  
  deinit {
    NotificationCenter.default.removeObserver(self)
  }
  
  // MARK: - IBActions
  
  @IBAction func restoreIAP(_ sender: UIBarButtonItem) {
    HUD.show(.labeledProgress(title: "请稍后", subtitle: nil))
    
    // restore iap
    SwiftyStoreKit.restorePurchases(atomically: true) { results in
      if results.restoreFailedPurchases.count > 0 {
        HUD.flash(.labeledError(title: "恢复内购失败", subtitle: "请重试"), delay: 1.5)
      } else if results.restoredPurchases.count > 0 {
        loggingPrint("Restore Success: \(results.restoredPurchases)")
        self.iapPurchaseBasicInfos = results.restoredPurchases.map {
          IAPPurchaseBasicInfo(productID: $0.productId, date: $0.transaction.transactionDate!)
        }
        
        let productIDs = results.restoredPurchases.map {
          $0.productId
        }.joined(separator: "|")
        
        // fetch iap contents from server
        API.shared.requestAPI (
          APIURLStrings.getiOSPurchasedContents(iapIdentifiers: productIDs),
          method: .get,
          header: API.shared.memeberHeader,
          successCallback: { json in
            if let contentsJSONArray = json["contents"].array {
              self.iapContents = contentsJSONArray.map {
                let productID = $0["product_id"].stringValue
                var date = Date()
                if let basicInfo = self.iapPurchaseBasicInfos?.first(where: {$0.productID == productID}) {
                  date = basicInfo.date
                }
                return Content (
                  date: date,
                  contentType: Content.ContentType(rawValue: $0["type"].stringValue)!,
                  id: $0["id"].stringValue,
                  name: $0["name"].stringValue,
                  coverURL: URL(string: "\(APIURLStrings.imagePrefix)\($0["cover"].stringValue)")!
                )
              }.sorted { return $0.date < $1.date }
              
              // save to coredata
              do {
                try IAPPurchasedItem.removeAll()
              } catch { }
              
              self.iapContents?.forEach {
                do {
                  try IAPPurchasedItem.add (
                    date: $0.date,
                    contentType: $0.contentType.rawValue,
                    id: $0.id,
                    name: $0.name,
                    coverURLString: $0.coverURL.absoluteString
                  )
                } catch { }
              }
              
              HUD.flash(.labeledSuccess(title: "恢复成功", subtitle: nil), delay: 1.5)
              self.tableView.reloadSections(IndexSet(integer: 2), with: .automatic)
              self.tableView.scrollToRow(at: IndexPath(row: 0, section: 1), at: .middle, animated: true)
            } else {
              HUD.flash(.labeledError(title: "无法获取节目信息", subtitle: "请重试"), delay: 1.5)
            }
        }, errorCallback: { (message, code) in
          HUD.flash(.labeledError(title: "无法获取节目信息", subtitle: "请重试"), delay: 1.5)
        })
      } else {
        HUD.flash(.label("没有内购内容"), delay: 1.5)
      }
    }
  }
  
  // MARK: - Public methods
  
  
  
}

extension PurchasedViewController: UITableViewDataSource {
  
  func numberOfSections(in tableView: UITableView) -> Int {
    return 3
  }
  
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0 {
      // exchanges
      if let count = exchangedContents?.count, count > 0 {
        return count
      } else {
        return 1
      }
    } else if section == 1 {
      // code
      if let count = codeContents?.count, count > 0 {
        return count
      } else {
        return 1
      }
    } else {
      // iap
      if let count = iapContents?.count, count > 0 {
        return count
      } else {
        return 1
      }
    }
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    func getNoDataCell(tip: String) -> NoDataTableCell {
      let cell = tableView.dequeueReusableCell(withIdentifier: noDataCellIdentifier, for: indexPath) as! NoDataTableCell
      cell.tipLabel.text = tip
      return cell
    }
    
    if indexPath.section == 0 {
      // exchanges
      if let count = exchangedContents?.count, count > 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: purchasedItemCellIdentifier, for: indexPath) as! PurchasedItemCell
        let exchangeContent = exchangedContents![indexPath.row]
        cell.prepare(coverImageURL: exchangeContent.coverURL, contentName: exchangeContent.name)
        return cell
      } else {
        return getNoDataCell(tip: "没有数据")
      }
    } else if indexPath.section == 1 {
      // code
      if let count = codeContents?.count, count > 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: purchasedItemCellIdentifier, for: indexPath) as! PurchasedItemCell
        let exchangeContent = codeContents![indexPath.row]
        cell.prepare(coverImageURL: exchangeContent.coverURL, contentName: exchangeContent.name)
        return cell
      } else {
        return getNoDataCell(tip: "没有数据")
      }
    } else {
      // iap
      if let count = iapContents?.count, count > 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: purchasedItemCellIdentifier, for: indexPath) as! PurchasedItemCell
        let iapContent = iapContents![indexPath.row]
        cell.prepare(coverImageURL: iapContent.coverURL, contentName: iapContent.name)
        return cell
      } else {
        return getNoDataCell(tip: "没有数据")
      }
    }
  }
  
  func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: purchasedHeaderViewIdentifier) as! PurchasedHeaderView
    if section == 0 {
      header.titleLabel.text = "狮羊曼尼兑换节目"
    } else if section == 1 {
      header.titleLabel.text = "鬼符兑换节目"
    } else {
      header.titleLabel.text = "iOS内购节目"
    }
    return header
  }
}

extension PurchasedViewController: UITableViewDelegate {
  
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    var content: Content? = nil
    if indexPath.section == 0 {
      if let count = exchangedContents?.count, count > 0 {
        content = exchangedContents![indexPath.row]
      }
    } else if indexPath.section == 1 {
      if let count = codeContents?.count, count > 0 {
        content = codeContents![indexPath.row]
      }
    } else {
      if let count = iapContents?.count, count > 0 {
        content = iapContents![indexPath.row]
      }
    }
    if content != nil {
      switch content!.contentType {
      case .group:
        selectedSimpleGroup = SimpleGroup(identifier: Int(content!.id)!, name: content!.name)
        performSegue(withIdentifier: "ShowGroupFromPurchased", sender: self)
        
      case .album:
        selectedAlbumIdentifier = Int(content!.id)!
        performSegue(withIdentifier: "ShowAlbumDetailFromPurchased", sender: self)
        break
      }
    }
    tableView.deselectRow(at: indexPath, animated: true)
  }
  
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.section == 0 {
      // exchanges
      if let count = exchangedContents?.count, count > 0 {
        return PurchasedItemCell.defaultHeight
      } else {
        return NoDataTableCell.defaultHeight
      }
    } else if indexPath.section == 1 {
      // code
      if let count = codeContents?.count, count > 0 {
        return PurchasedItemCell.defaultHeight
      } else {
        return NoDataTableCell.defaultHeight
      }
    } else {
      // iap
      if let count = iapContents?.count, count > 0 {
        return PurchasedItemCell.defaultHeight
      } else {
        return NoDataTableCell.defaultHeight
      }
    }
  }
  
  func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return PurchasedHeaderView.defaultHeight
  }
}
